/**
 * 
 */
package lt.vin.exaatto.client.ui;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import lt.vin.exaatto.client.events.ElementSelectedHandler;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

/**
 * @author Vincentas
 *
 */
public abstract class BaseContainerWidget<T> extends Composite implements ElementSelectedHandler<T> {

	private static BaseContainerWidgetUiBinder uiBinder = GWT.create(BaseContainerWidgetUiBinder.class);

	interface BaseContainerWidgetUiBinder extends UiBinder<Widget, BaseContainerWidget> {
	}
	
	@UiField
	Label label;
	
	@UiField
	VerticalPanel elementsPanel;
	
	@UiField
	PlaceholderTextBox textBox;
	
	private List<T> elements = new ArrayList<T>();
	
	private T selectedElement = null;

	public BaseContainerWidget(String label) {
		initWidget(uiBinder.createAndBindUi(this));
		
		this.label.setText(label);
		Stat.getHandlerManager().addHandler(ElementSelectedHandler.type, this);
	}
	
	protected void elementSelected(T element) {
		/*
		 * Do nothing by default
		 */
	}

	/**
	 * @param showAddButton the showAddButton to set
	 */
	public void setShowAddButton(boolean showAddButton) {
		textBox.setVisible(showAddButton);
	}

	@UiHandler("textBox")
	void onTextBoxBlur(BlurEvent e) {
		textBox.setText("");
	}
	
	@UiHandler("textBox")
	void onNewButtonClick(KeyPressEvent e) {
		if (KeyCodes.KEY_ENTER == e.getNativeEvent().getKeyCode()) {
			if (textBox.getText().length() != 0) {
				newTextEntered(textBox.getText());
				onTextBoxBlur(null);
			}
		} else if (KeyCodes.KEY_ESCAPE == e.getNativeEvent().getKeyCode()) {
			onTextBoxBlur(null);
		}
	}
	
	protected abstract void newTextEntered(String text);

	public List<T> getElements() {
		return new ArrayList<T>(elements);
	}

	public void setElements(Collection<T> elements) {
		clear();
		
		for (T element : elements) {
			addElement(element);
		}
	}
	
	public void clear() {
		elementsPanel.clear();
		this.elements.clear();
		selectedElement = null;
	}
	
	public void addElement(T element) {
		if (!elements.contains(element)) {
			elements.add(element);
			elementsPanel.add(createElementWidget(element));

			if (selectedElement == null) {
				markSelectedElement(element);
			}
		}
	}
	
	public void removeElement(T element) {
		if (elements.contains(element)) {
			elementsPanel.remove(elements.indexOf(element));
			elements.remove(element);

			if (element.equals(selectedElement)) {
				selectedElement = null;
				if (elements.size() > 0) {
					selectedElement(elements.get(0));
				}
			}
		}
	}
	
	protected ElementWidget<T> createElementWidget(T element) {
		 ElementWidget<T> elementWidget = new ElementWidget<T>(element, this);
		 
		 return elementWidget;
	}
	
	private static final String STYLE = "style.selected";
	
	public void markSelectedElement(T element) {
		if (selectedElement != null) {
			getElementWidget(selectedElement).removeStyleName(STYLE);
		}
		
		Widget elementWidget = getElementWidget(element);
		if (elementWidget != null) {
			selectedElement = element;
			elementWidget.addStyleName(STYLE);
		}
	}

	@Override
	public void selectedElement(T element) {
		markSelectedElement(element);
	}
	
	private Widget getElementWidget(T element) {
		Widget result = null;
		
		if (elements.contains(element)) {
			result = elementsPanel.getWidget(elements.indexOf(element));			
		}
		
		return result;
	}
	
	public void onRemoveElement(T element) {
		
	}

	
}
